package com.oscar.ehome.utils.dowload.dowload;

import android.content.ContentResolver;
import android.content.Context;
import android.content.Intent;
import android.net.ConnectivityManager;
import android.net.NetworkInfo;
import android.os.Handler;
import android.os.Message;

import com.oscar.ehome.bean.pagebean.StudyListBean;
import com.oscar.ehome.utils.dowload.db.DbDataOperation;
import com.oscar.ehome.utils.dowload.db.DbTags;
import com.oscar.ehome.utils.dowload.db.ThreadDAOImpl;
import com.oscar.ehome.utils.dowload.entity.TaskInfo;
import com.oscar.ehome.utils.dowload.entity.ThreadInfo;
import com.oscar.ehome.utils.util.ToastUtil;

import java.io.BufferedInputStream;
import java.io.File;
import java.io.IOException;
import java.io.RandomAccessFile;
import java.net.HttpURLConnection;
import java.net.MalformedURLException;
import java.net.ProtocolException;
import java.net.URL;
import java.util.LinkedList;
import java.util.List;
import java.util.Map;
import java.util.Observable;
import java.util.concurrent.ExecutorService;

public class DownloadTask extends Observable {

    /**
     * 默认启用线程的数量
     **/
    private static final int DEFAULT_THREAD_COUNT = 1;
    /**
     * 下载进度消息
     **/
    private static final int MSG_DOWNLOADING = 0x01;
    /**
     * 下载开始
     **/
    private static final int MSG_STARTDOWN = 0x02;

    private Context mContext;
    /**
     * 下载任务信息
     **/
    private TaskInfo mTaskInfo;
    /**
     * 线程数据库操作
     **/
    private ThreadDAOImpl mThreadDao;
    /**
     * 停止下载标志位
     **/
    private boolean isPause = false;
    /**
     * 启用下载线程数量
     **/
    private int mThreadCount = DEFAULT_THREAD_COUNT;
    /***
     * 保存各个线程的下载进度
     **/
    private int[] mTotalFinished;
    private Handler mHandler;
    /**
     * 线程池
     **/
    private ExecutorService mThreadPool;
    /**
     * 下载链接
     **/
    private String mStrDownloadUrl;
    /**
     * 下载文件id
     **/
    private String mStrDownloadId;
    private ContentResolver resolver;

    public String getUrl() {
        return this.mStrDownloadUrl;
    }

    public String getId() {
        return this.mStrDownloadId;
    }

    public boolean isPaused() {
        return isPause;
    }

    /**
     * 构造函数
     *
     * @param mContext    上下文
     * @param taskInfo    任务信息
     * @param threadPool  线程池
     * @param threadCount 开启的下载线程数
     */
    public DownloadTask(Context mContext, final TaskInfo taskInfo, ExecutorService threadPool, int threadCount) {
        this.mContext = mContext;
        this.mTaskInfo = taskInfo;
        this.mThreadPool = threadPool;
        this.mStrDownloadUrl = taskInfo.getUrl();
        this.mStrDownloadId = taskInfo.getBookid();
        resolver = mContext.getContentResolver();// 对外暴露数据共享
        init(threadCount);
    }

    /**
     * 初始化 初始化成员变量
     *
     * @param threadCount 开启的下载线程数
     */
    private void init(int threadCount) {
        mThreadDao = new ThreadDAOImpl(mContext);
        if (threadCount > 0) {
            mThreadCount = threadCount;
        }
        mTotalFinished = new int[mThreadCount];
        if (null == mHandler) {
            mHandler = new Handler() {
                @Override
                public void dispatchMessage(Message msg) {
                    OnDownload download = mTaskInfo.getDownload();
                    StudyListBean b = DbDataOperation.queryBook(resolver, DbTags.FIELD_BOOK_NAME, mTaskInfo.getFileName());// 查询book对象
                    if (b != null) {
                        ToastUtil.e("nm", "b.toString()" + b.toString());
                    }
                    if (null == download) {
                        return;
                    }
                    if (msg.what == MSG_STARTDOWN) {
                        download.onStrartDownloading(mTaskInfo.getUrl(), mTaskInfo.getBookid());
                        if (b != null) {
                            b.setVideoState(1);
                            DbDataOperation.updateDownloadState(resolver, 1, b.getMediaFile());// 1表示正在下载
                        }
                    } else if (msg.what == MSG_DOWNLOADING) {
                        int progress = (int) msg.obj; // 下载进度

                        // start 下载完成
                        if (progress == 100) {
                            File file = new File(mTaskInfo.getFilePath(), mTaskInfo.getFileName());
                            download.onDownloadFinished(file, progress);
                            sendBroadcastDownloadSuc();
                            if (b != null) {
                                b.setVideoState(3);
                                DbDataOperation.updateDownloadState(resolver, 4, b.getMediaFile());// 3表示下载完成
                                ToastUtil.e("vivi",
                                        "mTaskInfo.getBookid()" + mTaskInfo.getBookid() + "----mTaskInfo.getFileName();"
                                                + mTaskInfo.getFileName() + "mTaskInfo.getUrl()" + mTaskInfo.getUrl());
                            }
                            DownloadTask.this.setChanged();
                            DownloadTask.this.notifyObservers(progress);

                            // 广播下载完成
                            mThreadDao.deleteThread(mTaskInfo.getUrl()); // 删除数据库中存储的对应的线程信息
                        } else if (progress < 100) {

                            DownloadTask.this.setChanged();
                            DownloadTask.this.notifyObservers(progress);
                            download.onDownloading(mTaskInfo.getUrl(), progress, mTaskInfo.getBookid(),mTaskInfo.getPb()); // 执行回调，更新下载进度
                        }
                        // end 下载完成
                    }

                    super.dispatchMessage(msg);
                }
            };
        }
    }

    /**
     * 启动下载
     */
    public void downlaod() {

        List<ThreadInfo> threadInfoList = new LinkedList<ThreadInfo>(); // 建立线程信息列表//5
        threadInfoList = mThreadDao.getThread(mTaskInfo.getUrl()); // 从数据库中取出对应的线程信息

        // start 数据库没有对应的线程信息，则创建相应的线程信息
        if (threadInfoList.size() <= 0) {
            int block = mTaskInfo.getLenght() / mThreadCount; // 将下载文件分段
            if (block > 0) {
                // start 根据线程数量分别建立线程信息
                for (int i = 0; i < mThreadCount; i++) {

                    ThreadInfo info = new ThreadInfo(i, mTaskInfo.getUrl(), i * block, (i + 1) * block - 1, 0,
                            mTaskInfo.getBookid());
                    if (i == mThreadCount - 1) {
                        info.setEnd(mTaskInfo.getLenght()); // 分段最后一个，结束位置到文件总长度末尾
                    }
                    threadInfoList.add(info); // 加入列表
                    mThreadDao.insertThread(info); // 向数据库插入线程信息
                }
                // end 根据线程数量分别建立线程信息
            } else {
                ThreadInfo info = new ThreadInfo(0, mTaskInfo.getUrl(), 0, mTaskInfo.getLenght(), 0,
                        mTaskInfo.getBookid());
                threadInfoList.add(info);
                mThreadDao.insertThread(info);
            }
        }
        // end 数据库中没有对应的线程信息，则创建相应的线程信息

        // start 启动下载线程
        for (ThreadInfo info : threadInfoList) {
            DownloadThread thread = new DownloadThread(info);
            if (!mThreadPool.isShutdown()) {
                mThreadPool.execute(thread);
            }
        }
        // end 启动下载线程
    }

    /**
     * 广播通知，下载完成
     */
    private void sendBroadcastDownloadSuc() {
        Intent intent = new Intent();
        intent.setAction(DownloadService.ACTION_FINISHED);
        intent.putExtra(DownloadService.EXTRA_DOWNLOAD_URL, mTaskInfo.getUrl()); // 下载链接
        mContext.sendBroadcast(intent);
    }

    /**
     * 停止下载
     */
    public void pause() {
        isPause = true;
    }

    /**
     * 重新开始下载
     */
    public void restart() {
        isPause = false;
        downlaod();
    }

    /**
     * 下载线程
     */
    class DownloadThread extends Thread {
        private ThreadInfo threadInfo; // 线程信息

        public DownloadThread(ThreadInfo threadInfo) {
            this.threadInfo = threadInfo;
        }

        int d;

        @Override
        public void run() {

            notifyStart(); // 通知开始下载

            URL url = null;
            HttpURLConnection con = null; // http链接
            RandomAccessFile accessFile = null; // 下载文件
            try {

                int start = threadInfo.getStart() + threadInfo.getFinished(); // 读取文件的位置
                // start 初始化下载链接
                url = new URL(threadInfo.getUrl());
                con = (HttpURLConnection) url.openConnection();
                con.setRequestMethod("GET");
                con.setConnectTimeout(5000);
                con.setRequestProperty("Charset", "UTF-8");
                con.setRequestProperty("Range", "bytes=" + start + "-" + threadInfo.getEnd()); // 设置读取文件的位置，和结束位置,
                con.getHeaderFields();
                Map<String, List<String>> hea = con.getHeaderFields();
                for (String in : hea.keySet()) {
                    // map.keySet()返回的是所有key的值
                    List<String> str = hea.get(in);// 得到每个key多对用value的值
                }
                // end 初始化下载链接
                // start 初始化下载到本地的文件
                accessFile = new RandomAccessFile(new File(mTaskInfo.getFilePath(), mTaskInfo.getFileName()), "rwd");
                accessFile.seek(start); // 设置开始写入的位置
                if ((con.getResponseCode() == HttpURLConnection.HTTP_PARTIAL)
                        || (con.getResponseCode() == HttpURLConnection.HTTP_OK)) {
                    BufferedInputStream inputStream = new BufferedInputStream(con.getInputStream());
                    int finished = threadInfo.getFinished(); // 已经下载的长度
                    int readLen = 0; // 读取的长度
                    byte[] buffer = new byte[1024 * 4];
                    long time = System.currentTimeMillis();
                    int h = 0;
                    // start 读取输入流写入文件
                    while ((readLen = inputStream.read(buffer)) != -1) {
                        accessFile.write(buffer, 0, readLen);
                        finished += readLen;
                        h += readLen;
                        threadInfo.setFinished(finished); // 设置已经下载进度
                        if (System.currentTimeMillis() - time > 1000) {
                            notifyProgress(threadInfo.getId(), finished); // 每隔2秒通知下载进度
                            time = System.currentTimeMillis();
                        }
                        // start 停止下载，保存进度
                        // Log.d("params", "isPause"+isPause);
                        if (isPause) {
                            notifyProgress(threadInfo.getId(), finished); // 通知下载进度
                            threadInfo.setFinished(finished);
                            mThreadDao.updateThread(threadInfo.getUrl(), threadInfo.getId(), finished); // 更新数据库对应的线程信息
                            return;
                        }
                    }
                    notifyProgress(threadInfo.getId(), finished);
                }
            } catch (MalformedURLException e) {
                e.printStackTrace();
            } catch (ProtocolException e) {
                e.printStackTrace();
            } catch (IOException e) {
                e.printStackTrace();
            } finally {

                try {
                    if (accessFile != null) {
                        accessFile.close();
                    }
                    if (null != con) {
                        con.disconnect();
                    }

                } catch (IOException e) {
                    e.printStackTrace();
                }

            }
            super.run();
        }
    }

    /**
     * 通知下载进度
     *
     * @param threadId 线程id
     * @param finished 已经完成的进度
     */
    private synchronized void notifyProgress(int threadId, int finished) {
        if (threadId >= 0 && threadId < mTotalFinished.length) {
            mTotalFinished[threadId] = finished;
            int nowFinished = 0;
            for (int i = 0; i < mTotalFinished.length; i++) {
                nowFinished += mTotalFinished[i];
            }
            int progress = (int) (((float) nowFinished / (float) mTaskInfo.getLenght()) * 100);

            mHandler.sendMessage(mHandler.obtainMessage(MSG_DOWNLOADING, progress));
        }
    }

    private synchronized void notifyStart() {
        mHandler.sendMessage(mHandler.obtainMessage(MSG_STARTDOWN));
    }

    /**
     * 检测当的网络（WLAN、3G/2G）状态
     *
     * @param context Context
     * @return true 表示网络可用
     */
    public static boolean isNetworkAvailable(Context context) {
        ConnectivityManager connectivity = (ConnectivityManager) context.getSystemService(Context.CONNECTIVITY_SERVICE);
        if (connectivity != null) {
            NetworkInfo info = connectivity.getActiveNetworkInfo();
            if (info != null && info.isConnected()) {
                // 当前网络是连接的
                if (info.getState() == NetworkInfo.State.CONNECTED) {
                    // 当前所连接的网络可用
                    return true;
                }
            }
        }
        return false;
    }

}
